<!--before-submit-form
  :data.sync:双向绑定的操作数组变量名
mc-query-url:初始化表格的后台接口
mc-query-method： post get
:before-submit-form: 是一个事件方法 但是不要@  当返回true时，继续提交，否则不提交 beforeSubmitForm属性 参数 {form:提交的非vue数据,_form:当前表单vue对象}

mc-save-url:表单提交地址
mc-delete-url:

event:
@before-open-form({type:"insert"|edit",form:{表单对象}})
@before-create({query:{查询对象}})
当初始化表格数据时
@before-render-data({res:{返回的对象}})
@mc-page-change({currentPage,page,vue})
@scroll-to-botton({}) 滚动到底部
-->
<template>
    <div :class="rootClass" :data-magical__coder__id="dataMagical__coder__id">
      <el-row  class="mc-on-shade mc-vxe-table-row">
        <!--上下布局 没必要显示-->
        <el-col :xs="24" :md="mcLayout=='lr'?5:0" v-if="mcLayout=='lr'" class="mc-vxe-table-row-query-left">
          <slot name="query-left" :query="queryData" :row="queryData" :vue="mcTableVue" :parent="mcParentScope" :loading="axiosLoading"></slot>
        </el-col>
        <!--表格模块-->
        <el-col :xs="24" :md="mcLayout=='lr'?19:24">
          <el-row>
            <slot v-if="mcTopToolbar" name="operate" :vue="mcTableVue" :parent="mcParentScope"></slot>
            <el-col :span="24"  ref="queryRef" >
              <!-- 这个slot位置别换 不然遍历算法找不到query准备拿掉 row更统一-->
              <slot name="query" :query="queryData" :row="queryData" :vue="mcTableVue" :parent="mcParentScope"></slot>
            </el-col>
            <slot v-if="!mcTopToolbar" name="operate" :vue="mcTableVue" :parent="mcParentScope"></slot>
            <el-col :span="24" class="mc-vxe-table-col">
              <!--:custom-config="{storage: true}" 需要给表格一个id才能记住筛选-->
              <!--:scroll-x 把列动态渲染关掉 不然设计器里对应不上 很烦人-->
              <vxe-table :custom-config="{storage: mcStorage}" :scroll-x="{gt:1000}" :edit-rules="validRules"  class="mc-on-shade" :highlight-current-column="highlightCurrentColumnValue" :mc-table-vue="mcTableVue"
                         :print-config="getTablePrint()" :loading="loadingValue" @checkbox-change="checkBoxChange" @checkbox-all="checkBoxAll"
                         :highlight-current-row="true"  ref="vxeTable" :data="tableData" v-bind="$attrs" v-on="$listeners"
                         @cell-click="clickCell" @cell-dblclick="cellDbClick" @header-cell-click="headerCellClick" @header-cell-dblclick="headerCellDbClick"
              >
                <vxe-column fixed="left" type="checkbox" width="60" v-if="mcShowCheckbox"></vxe-column>
                <vxe-column type="seq" fixed="left" width="60" title="序号" v-if="mcShowOrderNo"></vxe-column>
                <slot></slot>
              </vxe-table>
            </el-col>
            <!--分页-->
            <el-col :span="24" v-if="mcShowPagination">
              <el-pagination layout="prev, pager, next, total, jumper" background :total="pageTotal" :page-size="pageSize" :current-page.sync="currentPage" @current-change="pageChange"
                             :pager-count="pageCount" :vue="mcTableVue"></el-pagination>
            </el-col>
          </el-row>
        </el-col>

        <!--弹窗-->
        <el-col :span="24" class="mc-vxe-table-dialog">
            <mc-dialog v-if="mcOpenPane.type=='dialog'" ref="dialog" :destroy-on-close="true"
             :show-close="true"
              :title="submitFormTitle"  mc-name="edit-dialog"
              :visible.sync="dialogVisible"
              @close="closeDialog"
               v-bind="mcOpenPane"
               :modal="mcOpenPane.modal"
               :close-on-click-modal="mcOpenPane.closeOnClickModal"
               :width="mcOpenPane.width"
              :height="mcOpenPane.height"
            >
                   <!-- 抛出form变量给父亲组件 v-if可以强制刷新 更实用 老是不刷新好烦啊 -->
                   <slot v-if="dialogVisible"  name="form" :form="formData" :row="formData" :vue="mcTableVue"  :parent="mcParentScope" :loading="axiosLoading"></slot>
                   <template #footer class="dialog-footer"  v-if="mcShowSubmitBar">
                     <slot name="dialog-footer" :vue="mcTableVue" :parent="mcParentScope" :loading="axiosLoading"></slot>
                       <el-button v-if="mcDialogFooterBtn" size="small" @click="closeDialog">取消</el-button>
                       <el-button v-if="mcDialogFooterBtn" size="small" type="primary" @click="submitForm" :icon="axiosLoading.save?'el-icon-loading':''" :disabled="axiosLoading.save">确定</el-button>
                   </template>
            </mc-dialog>

            <mc-drawer v-if="mcOpenPane.type=='drawer'"  :destroy-on-close="true"
              ref="drawer"   mc-name="edit-drawer"
             :show-close="true"
              :title="submitFormTitle"
              :visible.sync="dialogVisible"
              @close="closeDialog" v-bind="mcOpenPane"
               :modal="mcOpenPane.modal"
               :wrapper-closable="mcOpenPane.closeOnClickModal"
              :size="mcOpenPane.width">
                   <!-- 抛出form变量给父亲组件 scope.form准备去掉 统一row会很好理解  v-if可以强制刷新 更实用 老是不刷新好烦啊 -->
                   <slot ref="formRef" v-if="dialogVisible" name="form" :form="formData" :row="formData" :vue="mcTableVue" :parent="mcParentScope" :loading="axiosLoading"></slot>
                   <template #footer class="dialog-footer" v-if="mcShowSubmitBar">
                     <slot name="dialog-footer" :vue="mcTableVue" :parent="mcParentScope" :loading="axiosLoading"></slot>
                     <el-button v-if="mcDialogFooterBtn" size="small" @click="closeDialog">取消</el-button>
                     <el-button v-if="mcDialogFooterBtn" size="small" type="primary" @click="submitForm()" :icon="axiosLoading.save?'el-icon-loading':''" :disabled="axiosLoading.save">确定</el-button>
                   </template>
            </mc-drawer>

            <mc-dialog :destroy-on-close="true"
                       :show-close="true"
                       title="请选择导出数量" mc-name="excel"
                       :visible.sync="dialogExportNumVisible"
                       :close-on-click-modal="false"
                       height="220px"

            >
              <el-input v-model="exportExcelNum"></el-input>
              <template #footer class="dialog-footer"  v-if="mcShowSubmitBar">
                <el-button size="small" type="primary" @click="confirmExportExcel">确定</el-button>
              </template>
            </mc-dialog>

        </el-col>
        <!--子表-->
        <el-col :span="24">
           <slot name="parent" :parent="parentRowData" :row="parentRowData" :vue="mcTableVue"></slot>
        </el-col>
      </el-row>
    </div>
</template>

<script>
  import McDialog from "./McDialog.vue"
  import McDrawer from "./McDrawer.vue"
  import McCommon from "./McCommon";
//这一行在开发阶段加上即可 发布的时候去掉 不然打包会打入Vue好大
// import Vue from 'Vue'
  //https://github.com/SortableJS/Sortable#readme 这里import 打包会自动打进去 所以发布页面不要重复引入
  import Sortable from 'sortablejs';
var this_=null;
export default {
    name: 'mc-new-vxe-table',
    data () {
        return {
            dialogExportNumVisible:false,
            exportExcelNum:this.mcPageSize,
            exportExcelType:"",
            //拖拽行
            sortableTrIns:null,
            rendered:false,
            rootClass:(this.height=='auto'||(this.height+'').indexOf('%')!=-1)?'mc-vxe-table mc-on-shade mc-vxe-table-full-height':'mc-vxe-table mc-on-shade',
            //与mc-new-vxe-table-column共享
            mcTableVue:this,
            pageCount:this.mcPagerCount,//大于=5小于=21的奇数
            pageSize:this.mcPageSize,
            highlightCurrentColumnValue:window.iframeUi?true:this.highlightCurrentColumn,
            pageTotal:100,
            currentPage:1,
            dialogVisible:false,
            formData:{},
            formDataSnapshot:{},//用于还原数据使用
            queryData:this.mcInitQueryData,
            queryCondition : {},//查询条件比较符
            order:[],//排序
            submitFormTitle:"",
            loadingValue:this.loading,
            //孩子表需要的当前父亲这一行的数据
            parentRowData:{},

            //兼容老数据
            backendList:[],
            //加载中...
            axiosLoading:{
              query:false,
              save:false,
              delete:false,
              export:false
            },
            //校验规则
            validRules:{},
        }
    },
    inheritAttrs:false,
    props:
      {
        'dataMagical__coder__id':this.dataMagical__coder__id,
        /*布局 tb上下 lr左右*/
        'mcLayout':{type:String,default:'tb'},
        //找个莫名其妙的-10000来标记用户是否配置了data.sync属性 兼容老的组件 即使不配置data属性 也能跑起来 也别加类型
        'data':{},
        //静态删除的数组
        'apiDeleteData':{},
        //外键配置catalog,schema,table,pidName
        'mcFk':{},
        //反馈给外部的mcFk变量
        'mcFkValue':{},
        //级联表配置 _children:[{catalog,schema,table,pidName}] 子表配置
        'mcCascade':{},//
        //父亲scope名称 便于继承父亲的scope
        'mcParentScope':{},
        //版本号 v1还不支持data v2开始支持外面传data
        'mcVersion':{type:String,default:"v1"},
        /*是否显示提交面板的toolbar*/
        'mcShowSubmitBar':{type:Boolean,default:true},
        /*是否可以拖拽行 默认false*/
        'mcDragTrEnable':{type:Boolean,default:false},
        //初始化的查询参数
        'mcInitQueryData':{type:Object,default:function(){return {}}},
        //开启滚动
        'mcScrollEnable':{type:Boolean,default:false},
        //滚动类型 row:行滚动 pixel:像素滚动
        'mcScrollType':{type:String,default:"pixel"},
        //滚速
        'mcScrollSpeed':{type:Number,default:50},
        //页码数量
        'mcPagerCount':{type:Number,default:5},
        /*每页多少条*/
        'mcPageSize':{type:Number,default:10},
        /*每隔多少秒自动刷新*/
        'mcIntervalSeconds':{type:Number,default:0},
        /*请求数据*/
        'mcQueryUrl':{type:String},
        /*本身配置各种查询参数的 api:{orders:[{name:"name",type:"desc"}]}*/
        'mcConfig':{type:Object,default:function () {return {};}},
        /*导出数据*/
        'mcExportUrl':{type:String},
        /*请求方法*/
        'mcQueryMethod':{type:String,default:'post'},
        /*请求协议*/
        'mcQueryContentType':{type:String,default:'application/json'},
        /*其他post请求的协议*/
        'mcPostContentType':{type:String,default:'application/json'},
        /*表单提交*/
        'mcSaveUrl':{type:String},
        /*更新某个字段的值*/
        'mcUpdateUrl':{type:String},
        /*当查询表格数据前调用*/
        'beforeQueryTable':{type:Function,default:null},
        /*当提交表单存储数据前调用*/
        'beforeSubmitForm':{type:Function,default:null},
        /*自定义表单标题函数：type:edit|add*/
        'mcFormTitleFn':{type:Function,default:null},
        /*扩展的提交表单的数据*/
        'mcExtraSubmitData':{type:Object,default:null},
        /*删除一条记录地址*/
        'mcDeleteUrl':{type:String},
        //下面的功能父子表可用
        /*固定额外查询条件 其实就是parentRowData*/
        'mcFromParentQuery':{type:Object,default:null},
        /*外键父亲字段名 如果多个就逗号分隔  {'pid':'id'} 子表外键名:父亲键名 */
        'mcPidFieldMap':{type:Object,default:null},
        /*父亲表查询是否改变子表*/
        'mcParentQueryChangeChildren':{type:Boolean,default:true},
        /*显示加载中*/
        'loading':{type:Boolean,default:false},
        /*是否显示分页*/
        'mcShowPagination':{type:Boolean,default:true},
        /*是否显示复选框*/
        'mcShowCheckbox':{type:Boolean,default:true},
        /*是否显示序号*/
        'mcShowOrderNo':{type:Boolean,default:false},
        /*刚初始化后是否可查询*/
        'mcInitQuery':{type:Boolean,default:true},
        /*标记表格是否可以查询*/
        'mcMountQuery':{type:Boolean,default:true},
        'mcDialogFooterBtn':{type:Boolean,default:true},
        'highlightCurrentColumn':{type:Boolean,default:false},
        'mcWatch':{type:String,default:null},
        'mcStorage':{type:Boolean,default:true},
            //参数值 这样可以接受变量 表达式之类的，暂时20个足够使用了
        'mcv1':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv2':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv3':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv4':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv5':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv6':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv7':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv8':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv9':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv10':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv11':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv12':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv13':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv14':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv15':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv16':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv17':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv18':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv19':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        'mcv20':{type:[String,Number,Date,Boolean,Array,Object],default:null},
        //打开面板 dialog|drawer
        'mcOpenPane':{type:Object,default:function(){ return {type:'dialog',height:null,width:'70%',top:"15vh",modal:window.iframeUi?false:true,closeOnClickModal:true} }},
        'height':{type:String,default:null},
        //数组字段返回将被强转 前提是逗号分隔
        'mcArrayFields':{type:Array,default:null},
        'mcTopToolbar':{type:Boolean,default:false}
      },
      components:{
        McDialog,McDrawer
      },
      computed:{
        //这样就完全把tableData跟外部data属性双向绑定了 :data.sync="tableData"
        tableData:{
          get(){
            if(this.data||this.mcVersion=='v2'){//新版
              return this.data;
            }
            //兜底最老版本
            return this.backendList;
          },
          set(newData){
            if(this.data || this.mcVersion=='v2'){//新版
              this.$emit("update:data",newData);
              return;
            }
            this.backendList = newData;
          }
        }
      },
      watch:{
          mcFromParentQuery:{
            handler(newValue,oldValue){
              var NXID = newValue._XID||newValue._X_ROW_KEY
              var OXID = oldValue._XID||oldValue._X_ROW_KEY
                //说明只有父亲点击行 改变时才进行查询孩子 不然不查询
              if(!NXID){//没有点击父亲 就不要查询子表 统一清空
                if(this.mcParentQueryChangeChildren){
                  this.reset();
                }
              }else if(NXID!==OXID){
                this.reload({currentPage:1});
              }
                /*if(newValue._XID!==oldValue._XID){
                  this.currentPage=1;//重新从第一页开始刷新
                  if(!newValue._XID){//父亲点击查询 清空下孩子
                     this.reset();
                  }else {
                    //触发请求表格数据
                    this.reload();
                  }
                }else {
                  if(!newValue._XID){
                    this.reset();
                  }
                }*/
            },
            deep:false
          },
          tableData:{
            handler(newData){
              this.$emit("mc-on-data-change",{data:newData})
            },
            deep:true
          }
      },
      updated:function(){
          if(window.iframeUi&&window.iframeUi.jsonFactory){
            var _t = this;
            this.$nextTick(function(){//虚拟dom转化为真实dom后触发 这样动态新增的结构里 仍然可以被拖拽
              // console.log("刷新")
              //修复下弹窗面板 把我的id吃掉了
                var dragMcPane = window.iframeUi.jsonFactory.api().pubGetDragMcPaneName();
                var magicalCoderIdAttrName = window.iframeUi.jsonFactory.api().getMagicalCoderIdAttrName();
                var container = $("#magicalDragSceneGhost").length>0?$("#magicalDragSceneGhost") : $("#magicalDragScene");
                var needRefresh = false;
                container.find(".vxe-table").each(function(idx,item){
                    var mcid = $(this).parents(".mc-vxe-table").attr(magicalCoderIdAttrName);
                    var idMap = {};
                    $(this).find(".vxe-table-slots>div").each(function(i,slot){
                      var attrId = $(slot).attr(magicalCoderIdAttrName);
                      var title = $(slot).attr("mc-title");
                      idMap[title]=attrId;
                      //别删除
//                      $(slot).removeAttr(magicalCoderIdAttrName);
                    })
                    {//not fix row 非固定列
                      var row = $(this).find(".vxe-table--render-wrapper>.vxe-table--main-wrapper")
                        .find(".vxe-table--header-wrapper")
                        .find(".vxe-header--row");
                      row.find("th").each(function(i,th){
                        var title = $(th).find(".mc-vxe-table-header-title").attr("mc-title");
                        if(title && idMap[title]){
                          $(th).attr(magicalCoderIdAttrName,idMap[title])
                        }
                      })
                      row.addClass(dragMcPane);
                      row.attr(magicalCoderIdAttrName,mcid);
                    }
                    {//fix row 固定列
                      var row = $(this).find(".vxe-table--render-wrapper>.vxe-table--fixed-wrapper")
                        .find(".vxe-table--header-wrapper")
                        .find(".vxe-header--row");
                      row.find("th").each(function(i,th){
                        var title = $(th).find(".mc-vxe-table-header-title").attr("mc-title");
                        if(title && idMap[title]){
                          $(th).attr(magicalCoderIdAttrName,idMap[title])
                        }
                      })
                      row.addClass(dragMcPane);
                      row.attr(magicalCoderIdAttrName,mcid);
                    }
                    {//设置id便滚动条自动记住位置
                      if(_t.$refs.drawer){
                        $(_t.$refs.drawer.$el).find(".el-drawer__body").attr(magicalCoderIdAttrName,mcid);
                      }
                      if(_t.$refs.dialog){
                        $(_t.$refs.dialog.$el).find(".el-dialog__body").attr(magicalCoderIdAttrName,mcid);
                      }
                    }
                    needRefresh=true;

                })
                if(needRefresh){
                  McCommon.util.refreshDragEvent(_t);
                }
            })
          }
      },
      beforeCreate(){
        //this.$emit('before-create',{query:this.mcInitQueryData});
      },
      created(){
            //考虑下监听
           var _t = this;
           this.$nextTick(function(){//虚拟dom转化为真实dom后触发
              var pageVue = window.MC ? window.MC['vue'] : window.vueMc;
              if(typeof pageVue !='undefined' && pageVue && this.mcWatch){
                var watch = this.mcWatch;
                if(watch){
                    var watchVars = watch.trim().split(",");
                    for(var n=0;n<watchVars.length;n++){
                        var varName = watchVars[n];
                        pageVue.$watch(varName,function(n,o){
                            _t._reloadCurrentPage();
                        },{deep:true});
                    }
                }
            }
          })
           if(!window.iframeUi){//布局器内 接口都缓存了 自动刷新没意义 所以不在布局器内 才让定时刷新有效 !window.iframeUi是对的
              var _t = this;
              if(!this.mcIntervalSeconds){
                  return;
              }
              var intervalTimer = null;
              var mcIntervalSeconds = this.mcIntervalSeconds||0;
              if(mcIntervalSeconds>0){
                intervalTimer = window.setInterval(function (){
                  _t._reloadCurrentPage();
                }, mcIntervalSeconds*1000);
              }
              //布局器会主动清理此定时任务 避免重复注册
              if(intervalTimer&&window.iframeUi){
                  window._mcCacheIntervals.push(intervalTimer)
              }
          }

    },

      mounted () {
        this.initValue();
        var _this = this;
        this.$nextTick(function(){
          setTimeout(function(){//slot内加载速度比较慢，等待一会
            //绑定toolbar的方式 搜索一下
            var xToolBars = McCommon.util.searchNodes(_this,{tagName:"VxeToolbar"},1);
            if(xToolBars && xToolBars.length>0){
              if(_this.$refs.vxeTable){
                _this.$refs.vxeTable.connect(xToolBars[0])
              }
            }

            _this.queryCondition = _this.findQueryCondition();//遍历查询条件
            // _this.resetQueryData();
            if(_this.mcMountQuery && _this.mcInitQuery){//初始化后是否立即加载查询
                _this._reloadCurrentPage();
            }else {//需要初始化一下数据 不然tableData就未定义
              if(typeof _this.tableData=='undefined' || _this.tableData===null){
                _this._setTableData({flag:true,code:0,data:[],count:0})
              }else {
                _this.pageTotal = _this.tableData?_this.tableData.length:0;
              }
            }
            _this.$emit('after-table-mounted',{vue:_this});
          },800)
          //最后一个参数 可以让事件冒泡 也就是所有的组件滚动条都能监听
          window.addEventListener("scroll",this.scrollEvent,true)
        })
        this.autoScrollTask();
      // this.$refs['vxeTable'].scrollToRow();
    },
      destroyed(){
      window.removeEventListener('scroll',this.scrollEvent,true);
    },
      methods:{
        /*focusMe(e){
          debugger
          if(window.iframeUi) {
            try {window.iframeUi.fastKey._triggerClickElem(e);}catch(e1) {}
          }
        },*/
        getValidRules(){
          return this.validRules;
        },
        getTablePrint(){
          var _t = this;
          var tablePrint={
            // 自定义打印的样式示例
            beforePrintMethod: ({ content }) => {
              // 拦截打印之前，返回自定义的 html 内容 这打印的东西 并不是表格的内容 很坑啊
//                console.log(content)
              return  content
            },
              style: ''
          }
          return tablePrint;
        },

        // 行拖拽
        registerTrSortable () {
          if(!this.mcDragTrEnable || this.sortableTrIns!=null){
            return;
          }
          var _t = this;
          var _elDom = _t.$refs.vxeTable.$el;
          const el = _elDom.querySelectorAll('.vxe-table--body-wrapper > table > tbody')[0]
          this.sortableTrIns = new Sortable(el, {
            ghostClass: 'blue-background-class',
            setData: function (dataTransfer) {
              dataTransfer.setData('Text', '')
            },
            onStart: function (/**Event*/evt) {
              var oldIndex = evt.oldIndex;
              _t.$emit("mc-before-drag-tr",{vue:_t,data:_t.tableData,dragRow:_t.tableData[oldIndex],evt:evt,fromIndex:evt.oldIndex})

            },
            onEnd: evt => {
                var deleteRow = McCommon.util.deleteRow(_t.tableData,evt.oldIndex);
                McCommon.util.addRow(_t.tableData,deleteRow,evt.newIndex)
                //拖拽完 要用一个数组拷贝一下 不然拖拽的不生效 @很重要
                var newArray = _t.tableData.slice(0);
                _t.tableData = [];
                _t.$nextTick(function () {
                  _t.tableData = newArray;
                  _t.$nextTick(()=>{
                    _t.$emit("mc-after-drop-tr",{vue:_t,data:_t.tableData,dragRow:deleteRow,evt:evt,fromIndex:evt.oldIndex,toIndex:evt.newIndex})
                  })
                });
            }
          })
        },
        checkBoxChange(param){
          this.$emit("mc-checkbox-change",param);
        },
        checkBoxAll(param){
          this.$emit("mc-checkbox-all",param);
        },
        initValue(){
          this.mcOpenPane.modal = window.iframeUi?false:this.mcOpenPane.modal;
          this.$emit("update:mc-fk-value",this.mcFk);//同步一下这个数据
        },
        scrollEvent:function (e){
          if(!this.rendered){
            if(window.iframeUi){//这种滚动条优化 不适合在发布页使用
              this.rendered = this.queryTable();
            }
          }else {
            //这里必须放 不然还取消不了事件呢
            window.removeEventListener('scroll',this.scrollEvent,true)
          }
        },
        /*多列排序 Column调用的*/
        sortChange(param){
          var property = param.property;
          var order = param.order;
          //先删除
          for(var i=0;i<this.order.length;i++){
            var item = this.order[i];
            if(item[property]){
              this.order.splice(i,1);
              i--;
              continue
            }
          }
          if(order){//追加
            var map = {};
            map[property]=order;
            this.order.push(map);
          }
          this._reloadCurrentPage();//查询
        },
        autoScrollTask:function(){
            if(!this.mcScrollEnable){
              return;
            }
            var _t = this;
            var vxeTable = this.$refs['vxeTable'];
            var idx = 0;
            var timer = setInterval(()=>{
                var fullRow = vxeTable.fullDataRowIdData;
                var arr = [];
                for(var key in fullRow){
                  var row = fullRow[key].row;
                  arr.push(row);
                }
                if(arr.length>0){
                  if(this.mcScrollType=='row'){
                    vxeTable.scrollToRow(arr[idx]);
                    if(idx>=arr.length){
                      idx = 0;
                    }else {
                      idx +=1;
                    }
                  }else if(this.mcScrollType=='pixel'){
                    var children = vxeTable.$children;
                    var parentEl = null;
                    for(var i=0;i<children.length;i++){
                      var vnode = children[i];
                      var el = vnode.$el;
                      var clazz = el.getAttribute("class");
                      if(clazz && clazz.indexOf("vxe-table--body-wrapper")!=-1){
                        parentEl = el;
                        break;
                      }
                    }
                    if(parentEl){
                      var parentHeight = parentEl.offsetHeight;//容器视窗
                      var scrollTop = parentEl.scrollTop;//滚动条距离顶部高
                      var scrollHeight = parentEl.scrollHeight;//滚动条高度
                      if(scrollTop+parentHeight>=scrollHeight){//滚到底了
                        idx = 0;
                        _t.$emit("scroll-to-bottom",{vue:_t});
                      }else {
                        idx +=1;
                      }
                    }
                    vxeTable.scrollTo(0,idx);
                  }
                }
            },this.mcScrollSpeed)
            if(timer&&window.iframeUi){
                window._mcCacheIntervals.push(timer)
            }
        },
        afterQuery:function(data,successMsg){
            if(typeof data == 'undefined'){
              return false;
            }
            if(data){
                if(typeof data['code']!== 'undefined' && data.code===0){
                    if(successMsg){
                        this.$message({message:successMsg,type:"success"});
                        return true;
                    }
                }else{
                    if(data['desc']){//失败了 统一处理接口会弹窗 无需再弹
//                          this.$message.error(data.desc);
                        return false;
                    }
                }
            }
            return true;
        },
        editEvent:function(row){
            if(this.mcFormTitleFn){
              this.submitFormTitle = this.mcFormTitleFn({type:"edit"});
            }else {
              this.submitFormTitle = "编辑";
            }

            this.formDataSnapshot = JSON.parse(JSON.stringify(row));
            for(var key in this.formData){//不存在的置空
              if(typeof this.formDataSnapshot[key]==='undefined'){
                this.$set(this.formData,key,null);
              }
            }
            for(var key in this.formDataSnapshot){
              this.$set(this.formData,key,this.formDataSnapshot[key]);
            }
            this.beforeOpenForm('edit')
            this.afterOpenForm('edit')
        },
        //设置表单父亲外键字段的值
        setFormParentValue:function(formData){
            if(this.mcFromParentQuery){
                if(this.mcPidFieldMap){
                    for(var childName in this.mcPidFieldMap){
                      var parentName = this.mcPidFieldMap[childName];
                      var value = this.mcFromParentQuery[parentName];
                      this.$set(formData,childName,value);
                    }
                }
            }
        },
        /*新增*/
        insertData:function({form}){
            form = form||{}
            if(this.mcFormTitleFn){
              this.submitFormTitle = this.mcFormTitleFn({type:"insert"});
            }else {
              this.submitFormTitle = "新增";
            }
            for(var key in this.formData){
              this.$set(this.formData,key,null);
            }
            for(var key in form){
              this.$set(this.formData,key,form[key]);
            }

            this.beforeOpenForm('insert')
            this.formDataSnapshot = JSON.parse(JSON.stringify({}));
            this.setFormParentValue(form);//赋值父亲字段值
            this.afterOpenForm('insert')
        },
        beforeOpenForm:function (type) {
          this.$emit('before-open-form',{type:type,form:this.formData});
        },
        afterOpenForm:function (type) {
          this.dialogVisible = true;
          this.$nextTick(()=>{
            setTimeout(()=>{
              this.$emit('after-open-form',{type:type,form:this.formData});
            },300)
          })
        },
        removeEvent:function(row,index){
            var _t = this;
            if(!this.mcDeleteUrl){
                this.$message.error("请配置删除地址");
                return;
            }
            if(window.iframeUi){
              this.$message.error("设计阶段不进行删除，请在预览界面体验");
              return;
            }
            this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
                      confirmButtonText: '确定',
                      cancelButtonText: '取消',
                      type: 'warning'
                    }).then(() => {
                       _t.requestDeleteData({row,index});
                    }).catch(() => {
                      this.axiosLoading.delete = false;
                    });
        },
        requestDeleteData:function ({row,index,callback}) {
          this.axiosLoading.delete = true;
          var _t = this;
          var deleteData = this.deepCopyFromRow(row);
          _t.transeFormArrayFields(deleteData);
          _t.copyCascade(deleteData);
          _t.$magicaltool.request.axios({reject:false,$vue:_t,method:"post",url:this.mcDeleteUrl,data:deleteData,contentType:this.mcPostContentType,
          }).then(function(res) {
            if(_t.afterQuery(res)){
              _t.tableData.splice(index,1);
              _t.setParentRowData({});
            }
            if(callback){
              callback({res})
            }
            _t.axiosLoading.delete = false;
          }).catch(function (error) {
            console.log(error)
            _t.axiosLoading.delete = false;
          });
        },
        closeDialog:function(){
            /*for(var key in this.formDataSnapshot){
                this.formData[key] = this.formDataSnapshot[key];
            }*/
            this.dialogVisible = false;
        },
        transeFormArrayFields(saveData){
            {
              if(this.mcArrayFields){
                for(var j=0;j<this.mcArrayFields.length;j++){
                  var field = this.mcArrayFields[j];
                  if(saveData[field]){
                    saveData[field] = saveData[field].join(",");
                  }
                }
              }
            }
        },
        deepCopyFromRow(data){
            var saveData = {};
            for(var key in data){
                if(data[key]!== null){
                    saveData[key] = data[key];
                }
            }
            return saveData;
        },
        copyCascade:function (form) {
          if(this.mcCascade){
            for(var key in this.mcCascade){
              form[key] = this.mcCascade[key];
            }
          }
        },
        //表单提交
        submitForm: async function(param){

            param = param||{};
            if(typeof param.executeBeforeSubmitForm=='undefined'){
              param.executeBeforeSubmitForm=true;
            }
            var drawerVueComponent = this.$refs[this.mcOpenPane.type];

            var childrenTables = McCommon.util.searchNodes(drawerVueComponent,{tagName:"mc-new-vxe-table$"});
            if(childrenTables){
              for(var i=0;i<childrenTables.length;i++){
                var errMap = await childrenTables[i].asyncValidate({full:false})
                if(errMap){
                  this.$message({ type: 'error', message: '校验不通过！' })
                  return;
                }
              }
            }
            McCommon.util.elFormValidate(drawerVueComponent,this,()=>{
              this._beginSubmit(param);
            })
        },
        _beginSubmit:function(param){
            if(!this.mcSaveUrl){
                this.$message.error("请配置表单提交地址");
                return;
            }
            var saveData = this.deepCopyFromRow(this.formData);
            this.transeFormArrayFields(saveData);
            //提交表单前 增加用户自定义的表单数据
            if(this.mcExtraSubmitData){
              for(var key in this.mcExtraSubmitData){
                saveData[key]=this.mcExtraSubmitData[key];
              }
            }
            if(this.beforeSubmitForm && param.executeBeforeSubmitForm){//之所以不用$emit是因为我要返回数据 判断是否继续往下提交
                if(!this.beforeSubmitForm({form:saveData,_form:this.formData,vue:this})){
                    return;
                }
            }
            var _t = this;
          _t.axiosLoading.save = true;
          _t.$magicaltool.request.axios(
              {$vue:_t,reject:false,method:"post",url:this.mcSaveUrl,data:saveData,contentType:this.mcPostContentType,
                }).then(function(res) {
                    var success = _t.afterQuery(res,"操作成功");
                    if(success){
                      _t.$emit("after-submit-form",{res:res,success:success,formData:saveData})
                      _t.dialogVisible = false;

                      if(_t.submitFormTitle=='新增' || _t.submitFormTitle=='编辑'){//刷新下表格
                        _t._reloadCurrentPage();
                      }else{
                        var extra = _t.pkHelper().initInRow(res.data);
                        _t.autoSetPkValue(_t.tableData,extra.pkColConfigMap);
                      }
                    }
                  _t.axiosLoading.save = false;
            }).catch(function (error) {
                console.log(error)
                _t.axiosLoading.save = false;
            });
        },
        buildMcDataUrl:function(){
            if(this.mcQueryUrl){
                var newArr = [];
                var arr = this.mcQueryUrl.split("?");
                newArr.push(arr[0]);
                if(arr.length<=1){
                    return this.mcQueryUrl+"?page="+this.currentPage+"&limit="+this.pageSize;
                }
                var paramMap = [];
                var arr2 = arr[1].split("&");
                var findPage = false,findLimit=false;
                for(var i=0;i<arr2.length;i++){
                    var arr3 = arr2[i].split("=");
                    if(arr3[0]=='page'){
                        findPage = true;
                        paramMap.push("page="+this.currentPage);
                    }else if(arr3[0]=='limit'){
                        findLimit = true;
                        paramMap.push("limit="+this.pageSize);
                    }else{
                        paramMap.push(arr2[i]);
                    }
                }
                if(!findPage){
                    paramMap.push("page="+this.currentPage);
                }
                if(!findLimit){
                    paramMap.push("limit="+this.pageSize);
                }
                newArr.push(paramMap.join("&"))
                return  newArr.join("?");
            }
            return "";
        },
        buildMcExportUrl:function(type){
          if(this.mcExportUrl){
            /*if(type=='all'){//是否导出此次查询的所有数据
              return this.mcExportUrl;
            }*/
            var newArr = [];
            var arr = this.mcExportUrl.split("?");
            newArr.push(arr[0]);
            var limit = this.exportExcelNum;
            if(arr.length<=1){
              return this.mcExportUrl+"?page="+this.currentPage+"&limit="+limit;
            }
            var paramMap = [];
            var arr2 = arr[1].split("&");
            var findPage = false,findLimit=false;
            for(var i=0;i<arr2.length;i++){
              var arr3 = arr2[i].split("=");
              if(arr3[0]=='page'){
                findPage = true;
                paramMap.push("page="+this.currentPage);
              }else if(arr3[0]=='limit'){
                findLimit = true;
                paramMap.push("limit="+limit);
              }else{
                paramMap.push(arr2[i]);
              }
            }
            if(!findPage){
              paramMap.push("page="+this.currentPage);
            }
            if(!findLimit){
              paramMap.push("limit="+limit);
            }
            newArr.push(paramMap.join("&"))
            return  newArr.join("?");
          }
          return "";
        },
        buildQueryData:function(data){
            var newData = {};
            if(data){
                for(var key in data){
                    var value = data[key];
                    if(value !== null && value !== "" && typeof value != 'undefined' ){//忽略这些查询条件入参
                        newData[key] = value;
                    }
                }
            }
            if(this.mcFromParentQuery){
                if(this.mcPidFieldMap){
                    for(var childName in this.mcPidFieldMap){
                      var parentName = this.mcPidFieldMap[childName]
                      var value = this.mcFromParentQuery[parentName];
                      if(value !== null && value !== "" && typeof value != 'undefined'){
                          newData[childName] = value;
                      }
                    }
                }
            }
            return newData;
        },
        //预览模式
        showAllDataList(){
          return !window.iframeUi;
        },
        getAxiosParam(){
          var result = {};
          var request = this.$magicaltool.request;
          var url = this.buildMcDataUrl();
          var contentType = this.mcQueryContentType;
          if(url) {
            var ncv = request.util.collectMcNameCompareValue(this);
            var param = request.util.paramsTomMcQuery(ncv);
            var queryData = this.buildQueryData(this.queryData);
            //合并下 配置与查询表单
            for (var key in queryData) {
              param.param[key] = queryData[key];
            }
            for (var key in this.queryCondition) {
              param.condition[key] = this.queryCondition[key];
            }
            if(this.order && this.order.length>0){//手动控制了排序 就按手动排序算
              param.order = this.order;//排序
            }else {//使用默认排序规则
              if(this.mcConfig && this.mcConfig.api&&this.mcConfig.api.orders){
                param.order = request.util.mcQueryOrder(this.mcConfig.api.orders);
              }
            }
            if (!request.util.isMcQueryUrl(url) && !request.util.isContentTypeJson(contentType)) {
              //额外增加查询条件给用户
              param.param.condition_ = JSON.stringify(param.condition);
              param.param.order_ = JSON.stringify(param.order);
              param = param.param;//简单传递下表单参数
            }
            result.param = param;
          }
          result.url = url;
          result.method = this.mcQueryMethod;
          result.contentType = contentType;
          result.request = request;
          return result;
        },
        _reloadCurrentPage:function () {
          this.reload({currentPage:this.currentPage})
        },
        reload:function (param){
          this.$nextTick(()=>{
            this.queryTable(param);
          })
        },
        setParentRowData(data){
          this.parentRowData = data;
        },
        //{currentPage:当前页,pageTotal:总记录数};后面这个别加 不然导出excel条件就不一致了 query:{额外查询参数}
        //查询功能
        queryTable:function(param){
          //清理一波孩子
          this.setParentRowData({});
          param = param||{};
          {
            if(typeof param.currentPage!='undefined'){
              this.currentPage = param.currentPage;
            }else if(typeof param.current!='undefined' && param.current){//默认当前页刷新 针对于分页场景
            }else {
              this.currentPage = 1;//默认第一页数据
            }
            if(typeof param.pageTotal!='undefined'){
              this.pageTotal = param.pageTotal;
            }
          }
          {
            if(!McCommon.util.isInWindowView(this.$el)){
              return false;
            }
            this.rendered = true;
            //一定要解绑 当组件被渲染过一次时 滚动监听就不再需要了 懒加载过了 还滚动啥
            window.removeEventListener('scroll',this.scrollEvent,true)
          }
          if(!this.mcMountQuery){//表格是否允许请求ajax查询
            return true;
          }
            var result = this.getAxiosParam();
            if(result.url){
                var _t = this;
                if(this.beforeQueryTable){
                  //回调函数 如果返回false则中止查询
                  if(!this.beforeQueryTable({vue:this,request:result})){
                    return false;
                  }
                }
                this.loadingValue = true;
                result.request.axios({cache:true,$vue:this,url:result.url,method:result.method,param:result.param,contentType:result.contentType,reject:false}).
                then(function(res){
                  if(res['code']!==0){
                    _t.loadingValue=false;
                    return ;
                  }
                  _t._setTableData(res);
                            //把父组件的删除数据给清空一下
                  _t.apiSetDeleteData({data:[]})
                  _t.loadingValue=false;
                })
            }
          return true;
        },
        _setTableData:function(res){
          var _t = this;
          //批量追加辅助数据
     //数组字段 转下
          _t.transeTableArrayFields(res.data);
          _t.$emit("before-render-data",{res:res,vue:_t});
          _t.afterQuery(res);
          if(typeof res['count']!=='undefined'){
            _t.pageTotal = res.count;
          }
          var extra = _t.pkHelper().initInRow(res.data);
          if(_t.showAllDataList()){
            _t.tableData = extra.list;
          }else {//设计阶段仅展示一条数据
            //这里会有一个问题：如果返回的数据为空，就报错，所以要提醒用户先增加一条数据
            // _t.$message({type:"warning",message:"设计阶段仅展示一条数据"});
            if(extra.list && extra.list.length>0){
              _t.tableData = [extra.list[0]];
            }else{
              _t.tableData = McCommon.util.addMcExtraToList([{}]);
              //_t.$message({type:"warning",message:"表格至少需要有一条数据才能进行设计,您可以先添加一条数据"})
            }
          }

          //这个东西不能去掉 不然外键就出不来了
          _t.$nextTick(()=>{
              _t.autoSetPkValue(_t.tableData,extra.pkColConfigMap);
              _t.registerTrSortable();
            _t.$emit("after-render-data",{res:res,vue:_t});
          })
        },
        //刷一波
        render:function () {
          var _t = this;
          var extra = this.pkHelper().initInRow(this.tableData);
          _t.$nextTick(()=>{
            _t.autoSetPkValue(_t.tableData,extra.pkColConfigMap);
          })
        },
        transeTableArrayFields(data){
            if(this.mcArrayFields){
              if(data){
                for(var i=0;i<data.length;i++){
                  var item = data[i];
                  for(var j=0;j<this.mcArrayFields.length;j++){
                    var field = this.mcArrayFields[j];
                    if(item[field]){
                      item[field] = item[field].split(",");
                    }
                  }
                }
              }
            }
        },
      //type:all 所有数据 page:当前页
        exportExcel:function(type){
          this.exportExcelType = type;
          if(type=='all'){
            this.dialogExportNumVisible=true;
          }else {
            this.exportExcelNum=this.pageSize;
            this.confirmExportExcel();
          }
        },
        confirmExportExcel:function () {
          var url = this.buildMcExportUrl(this.exportExcelType);
          if(url){
            var result = this.getAxiosParam();
            if(this.beforeQueryTable){
              //回调函数 如果返回false则中止查询
              if(!this.beforeQueryTable({vue:this,request:result})){
                return false;
              }
            }
            result.url = url;
            //必须加上blob不然不行
            result.request.axios({responseType:'blob',cache:true,$vue:this,url:result.url,method:result.method,param:result.param,contentType:result.contentType}).
            then(res=>{
              // this.queryTable();
            })
          }else {
            this.$message({type:"warning",message:"您还未配置导出Excel地址"})
          }
          this.dialogExportNumVisible=false;
        },
        //外键助手
        pkHelper:function(){
            var _t = this;
            var request = this.$magicaltool.request;
            var util = {
                initInRow:function(list){
                    var pkColConfigMap = this.findAllPkFieldMap();
                    if(list && list.length>0){
                        for(var i=0;i<list.length;i++){
                            var row = list[i];
                            //visible可以给行弹窗使用的
                            row._mcExtra={pk:this.buildDefaultPk(pkColConfigMap),print:{},titleText:{}};//pk是外键表信息 {pid:{id:1,name:""}} 把整个父亲表信息都存储在此处了 text:{"title取列标题":"xxx"}
                            McCommon.util.addMcExtra(row._mcExtra);
                        }
                    }
                    return {list:list,pkColConfigMap:pkColConfigMap};
                },
                buildDefaultPk:function(pkColConfigMap){
                    var map = {};
                    for(var field in pkColConfigMap){
                        map[field] = "";
                    }
                    return map;
                },
                addPk:function(row,key,value){
                    row._mcExtra.pk[key]=value;
                },
                findAllPkFieldMap:function(){
                    var pkColConfigMap = {}
                    var vxeTable = _t.$refs['vxeTable'];
                    if(vxeTable){
                      var children = vxeTable.$children;
                      for(var i=0;i<children.length;i++){
                        var child = children[i];
                        var mcColConfig = child.mcColConfig;
                        if(mcColConfig){
                          var type = mcColConfig.type;
                          var field = child.field;
                          var pkField = mcColConfig.pkField;//外键父亲的主键名
                          var pkTextField = mcColConfig.pkTextField;//即将友好展示的父亲字段文本
                          switch(type){
                            case 'pk':
                              pkColConfigMap[field] = mcColConfig;
                              break;
                          }
                        }
                      }
                    }
                    return pkColConfigMap;
                },
                findIdList : function(tableData,field){
                    var pkIdMap = {};
                    for(var i=0;i<tableData.length;i++){
                       var item = tableData[i];
                       var v = item[field];
                       if(typeof v!='undefined' && v!==null && v!==''){
                          pkIdMap[v]=v
                       }
                    }
                    var idList = [];
                    for(var key in pkIdMap){
                        idList.push(pkIdMap[key]);
                    }
                    return idList;
                },
                buildParam : function(mcColConfig,idList){
                    var pkField = mcColConfig.pkField;//外键父亲的主键名
                    var pkTextField = mcColConfig.pkTextField;//即将友好展示的父亲字段文本
                    var param = {};
                    if(request.util.isMcQueryUrl(mcColConfig.api.url) || request.util.isContentTypeJson(mcColConfig.api.contentType)){
                        param = request.util.paramsTomMcQuery(mcColConfig.api.params)
                        param.param[pkField] = idList;
                        param.condition[pkField] = "in";
                        if(mcColConfig.api.fields && mcColConfig.api.fields.length>0){
                            param.fields = mcColConfig.api.fields
                        }
                    }else{//用户自己的url 仅仅传参数 不传查询条件
                        param = request.util.paramsToJson(mcColConfig.api.params)
                        param[pkField] = idList;
                    }
                    return param;
                },
                buildMethod : function(mcColConfig){
                    if(request.util.isMcQueryUrl(mcColConfig.api.url)){
                        return 'post';
                    }
                    return mcColConfig.api.method;
                }

            }
            return util;
        },
        //自动设置外键值
        autoSetPkValue(tableData,pkColConfigMap){
            var _t = this;
            //遍历一下外键的ids
            for(var field in pkColConfigMap){
                var mcColConfig = pkColConfigMap[field];
                var pkField = mcColConfig.pkField;//外键父亲的主键名
                var pkTextField = mcColConfig.pkTextField;//即将友好展示的父亲字段文本
                var idList = this.pkHelper().findIdList(tableData,field);
                if(idList && idList.length>0){
                  var param = this.pkHelper().buildParam(mcColConfig,idList);
                  var method = this.pkHelper().buildMethod(mcColConfig);
                  this.ajaxSetPkValue(field,mcColConfig,param,method,pkField,pkTextField,tableData)
                }
            }
        },
        ajaxSetPkValue(field,mcColConfig,param,method,pkField,pkTextField,tableData){
            var _t = this;
            _t.$magicaltool.request.axios({contentType:mcColConfig.api.contentType,$vue:this,method:method,url:mcColConfig.api.url,data:param})
                .then((res)=>{
                    if(res.code==0){
                        var pkDataList = res.data;
                        if(pkDataList && pkDataList.length>0){
                            var pkDataMap = {};
                            for(var i=0;i<pkDataList.length;i++){
                                var item = pkDataList[i];
                                pkDataMap[item[pkField]] = item;
                            }
                            //开始重新渲染表格数据
                            for(var i=0;i<tableData.length;i++){
                               var row = tableData[i];
                               var v = row[field];
                               if(typeof v!='undefined' && v!==null && v!==''){
                                  _t.pkHelper().addPk(row,field,pkDataMap[v])
                               }
                            }
                        }
                    }
                })
        },
        /*页面点击*/
        pageChange:function(page){
            //点击切换页码前
            this.$emit("mc-page-change",{vue:this,currentPage:this.currentPage,page:page})
            this._reloadCurrentPage();
        },
        resetQueryData:function(){
            this.queryData = {};
            this.order=[];
            //清空选中状态
            var columns = this.getMcVxeTableColumns();
            for(var i=0;i<columns.length;i++){
                columns[i].resetOrder();
            }
        },
        //重置下表格
        reset:function () {
          this.tableData=[];
          this.currentPage=1;
          this.pageTotal=0;
        },
        getTable:function (){
          return this.$refs.vxeTable;
        },
       //获取所有列vue对象 父子组件通信
        getMcVxeTableColumns:function (){
          var array = [];
          var columns = this.getTable().$children;
          for(var i=0;i<columns.length;i++){
            if(columns[i]['resetOrder']){
              array.push(columns[i]);
              columns[i].resetOrder();
            }
          }
          return array;
        },
        findQueryCondition:function(){
            var queryRef = this.$refs['queryRef'];
            var conditionMap = {};
            this.iteratorChildren(queryRef,conditionMap);//查询区域会被
            /*if(queryRef && queryRef.$slots.default){
                var querySlot = queryRef.$slots.default[0];
                if(querySlot.componentInstance){
                    this.iteratorChildren(querySlot.componentInstance,conditionMap);
                }
            }*/
            return conditionMap;
        },
        //递归算法 查找查询条件
        iteratorChildren:function(component,valueMap){
            if(component){
                var mcCondition = component.$attrs['mc-condition'];
                if(mcCondition){
                    var vnode =  component._self.$vnode;
                    var data = vnode.data;
                    if(data['model']){//v-model藏得太深了 注意上传文件这里没搞 TODO
                      var expression = data.model.expression;
                      if(expression.indexOf(".")!=-1){
                          var arr = expression.split(".");
                          valueMap[arr[arr.length-1]] = mcCondition;
                      }
                    }
                }

                var children = component.$children;
                if(children&& children.length>0){
                    for(var i=0;i<children.length;i++){
                        this.iteratorChildren(children[i],valueMap);
                    }
                }
            }
        },
        clickCell(cellData){
            var rowIndex = cellData.rowIndex;
            this.setParentRowData(cellData.data[rowIndex]);
            this.$emit("mc-cell-click",cellData)
            this.refreshUnDownChildrenTables();
//            this.$refs.vxeTable.setCurrentRow(this.tableData[1]);//高亮当前行
        },
        clickRow(param){
          var {rowIndex}=param;
          if(this.tableData.length>0){
            this.setParentRowData(this.tableData[rowIndex]);
            this.refreshUnDownChildrenTables();
            this.$refs.vxeTable.setCurrentRow(this.tableData[rowIndex]);//高亮当前行
          }else {
            console.log("表格为空，暂未执行点击行")
          }
        },
        //刷新上下结构子表
        refreshUnDownChildrenTables(){

        },
        cellDbClick(cellData){
          this.$emit("mc-cell-dblclick",cellData);
        },
        headerCellClick(data){
          this.$emit("mc-header-cell-click",data)
        },
        headerCellDbClick(data){
          this.$emit("mc-header-cell-dblclick",data)
        },
        operateTableData(type){
          var printData = this.tableData;
          switch(type){
            case 'checked':
              printData = this.$refs.vxeTable.getCheckboxRecords();
              if(printData.length<=0){
                this.$message("请勾选要打印的行");
                return;
              }
              break;
          }

          var columns = []
          var table = this.$refs.vxeTable;
          var slots = table.$slots;
          if(slots.default){
            var defaultSlots = slots.default;
            for(var i=0;i<defaultSlots.length;i++){
              var node = defaultSlots[i];
              if(node.child && node.child.field){
                var attrs = node.child.$attrs;
                columns.push({width:attrs.width||node.child.width,title:attrs.title||node.child.title,field:node.child.field})
              }
            }
          }
          return {data:printData,columns:columns}
        },
        printTable(type){
           var operateTableData = this.operateTableData(type);
           var printData = operateTableData.data;
           var columns = operateTableData.columns;
           //获取表格的基础样式
           var table = this.$refs.vxeTable;
           var tableClassName = table.$el.className;
           //把上面import Vue打开
           var htmlVue = new Vue({
                     template:
                     `
                     <div>
                        <table :class="tableClassName+' is--print'" border="0" cellspacing="0" cellpadding="0">
                          <colgroup>
                          <col :style="calcStyle(col)" v-for="(col,idx) in columns" :key="idx">
                          </colgroup>
                          <thead>
                          <th colspan="1" rowspan="1" v-for="(col,idx) in columns" :key="idx" :title="col.title"><div><span>{{col.title}}</span></div></th>
                          </thead>
                          <tbody>
                          <tr v-for="(row,idx) in printData" :key="idx">
                              <td colspan="1" rowspan="1"  v-for="(column,idx) in columns" :key="idx"><div>{{row._mcExtra.print[column.field]}}</div></td>
                          </tr>
                          </tbody>
                        </table>
                     </div>
                     `
                     ,
                     el: document.createElement('div'),
                     data:{
                         printData:printData,
                         columns:columns,
                         tableClassName:tableClassName
                     },
                     methods:{
                         calcStyle(col){
                            var style = []
                            if(col.width){
                                style.push("width:"+col.width+"px");
                            }
                            return style.join(";");
                         }
                     }
             })
          var html = htmlVue.$el.innerHTML
          this.$refs.vxeTable.print({
            beforePrintMethod: ({content}) => {
                return html;
            }
          });
        },
        exportTable(type){
            var operateTableData = this.operateTableData(type);
            var data = operateTableData.data;
            var columns = operateTableData.columns;
            var exportData = [];
            for(var i=0;i<data.length;i++){
              var row = data[i];
              exportData.push(row._mcExtra.titleText);
            }
            this.exportToCvs(columns,exportData);

        },
        formatData(date,fmt) {
          var o = {
            "M+": date.getMonth() + 1, //月份
            "d+": date.getDate(), //日
            "H+": date.getHours(), //小时
            "m+": date.getMinutes(), //分
            "s+": date.getSeconds(), //秒
            "q+": Math.floor((date.getMonth() + 3) / 3), //季度
            "S": date.getMilliseconds() //毫秒
          };
          if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
          for (var k in o)
            if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
          return fmt;
        },
        //这个导出的数据列太多 应该导出跟表格完全一样的数据才对  TODO 而不是json数据
       exportToCvs(columns,jsonData){
         var arr = [];
         for(var i=0;i<columns.length;i++){
           arr.push(columns[i].title)
         }
        //列标题，逗号隔开，每一个逗号就是隔开一个单元格
        let str = arr.join(",")+'\n';
        //增加\t为了不让表格显示科学计数法或者其他格式
        for(let i = 0 ; i < jsonData.length ; i++ ){
          for(var j=0;j<columns.length;j++){
            var title = columns[j].title;
            if(jsonData[i][title]){
              str+=jsonData[i][title] + '\t,';
            }else {
              str+=  '\t,';
            }
          }
          str+='\n';
        }
        //encodeURIComponent解决中文乱码
        let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
        //通过创建a标签实现
        let link = document.createElement("a");
        link.href = uri;
        //对下载的文件命名
        link.download =  this.formatData(new Date(),"MMdd-HHmmss")+".csv";
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      },
      //__开头的方法不对外
      __dbUpdate:function({data,callback,confirm}){
          if(!this.mcUpdateUrl){
                this.$message.error("请配置表单更新地址");
                return;
            }
          var _t = this;
          _t.$magicaltool.request.axios(
            {$vue:_t,method:"post",url:this.mcUpdateUrl,data:data,contentType:this.mcPostContentType,
              }).then(function(res) {
                  if(callback){
                    callback({res});
                  }else{
                    _t.afterQuery(res,"操作成功");
                  }
          }).catch(function (error) {
              console.log(error)
          });
      },
      __dbSave:function({data,callback,confirm}){
            if(!this.mcSaveUrl){
                this.$message.error("请配置表单保存地址");
                return;
            }
            var _t = this;
            _t.$magicaltool.request.axios(
              {$vue:_t,method:"post",url:this.mcSaveUrl,data:data,contentType:this.mcPostContentType,
                }).then(function(res) {
                     if(callback){
                       callback({res});
                     }else{
                        _t.afterQuery(res,"操作成功");
                     }
            }).catch(function (error) {
                console.log(error)
            });
      },
      __dbDelete:function({data,callback,index}){
          var _t = this;
            _t.$magicaltool.request.axios({$vue:_t,method:"post",url:this.mcDeleteUrl,data:data,contentType:this.mcPostContentType,
              }).then(function(res) {
                if(typeof index!='undefined'){
                  _t.tableData.splice(index,1);
                }
                if(callback){
                  callback({res});
                }else{
                  _t.afterQuery(res,"操作成功");
                }
          }).catch(function (error) {
              console.log(error)
          });
      },
      //以下api暴露出去
        /**
         * 更新某个字段 空属性不会存储
         * data:要更新的实体 自行传入主键和更新的内容 {id:1,name:"更新值"}
         */
        dbUpdate:function({data,callback,confirm}){
            var _t = this;
            if(confirm){
              this.$confirm( '确定要更新？','提示').then(() => {
                    _t.__dbUpdate({data,callback,confirm})
                }).catch(()=>{
                  _t._reloadCurrentPage();
                })
            }else{
              _t.__dbUpdate({data,callback,confirm})
            }
        },
        dbSave:function({data,callback,confirm}){
            var _t = this;
            if(confirm){
              this.$confirm( '请确定是否继续操作？','提示').then(() => {
                    _t.__dbSave({data,callback,confirm})
                }).catch(()=>{
                  _t._reloadCurrentPage();
                })
            }else{
              _t.__dbSave({data,callback,confirm})
            }
        },
        dbDelete:function({data,index,callback,confirm}){
           var _t = this;
            if(confirm){
              this.$confirm( '确定要删除？','提示').then(() => {
                    _t.requestDeleteData({row:data,callback,index})
                })
            }else{
              _t.requestDeleteData({row:data,callback,index})
            }
        },
        getRowIdFromRowData(entity){
          return entity._XID||entity._X_ROW_KEY;
        },
        getData:function (){
          return this.tableData;
        },
        getQuery:function (){
          return this.queryData;
        },
        getApiDeleteData:function(){
            return this.apiDeleteData;
        },
        getCurrentPage:function () {
          return this.currentPage;
        },
        //兼容老的api 未来废弃
        addRow:function(entity,idx){
            McCommon.util.addRow(this.tableData,entity,idx)
        },
        //兼容老的api 未来废弃
        deleteRow:function(idx){
            McCommon.util.deleteRow(this.tableData,idx)
        },
        //api开头表示不操作库
        apiAddRow:function({data,index}){
            McCommon.util.addRow(this.tableData,data,index)
        },
        /**
         * index:删除的行索引
         * pk:主键名称 比如id 因为删除主键记录到删除数组里才有意义，方便数据库操作
         */
        apiDeleteRow:function({index,pk}){
            var deleteRow = McCommon.util.deleteRow(this.tableData,index)
            if(pk){//指定了主键并且存在
              if(deleteRow[pk]){
                if(this.apiDeleteData){
                  this.apiDeleteData.push(deleteRow);
                }else{
                  this.$emit("update:api-delete-data",[])
                  this.$nextTick(()=>{
                    if(this.apiDeleteData){
                        this.apiDeleteData.push(deleteRow);
                    }
                  })
                }
              }
            }
        },
        apiSetDeleteData:function({data}){
          this.$emit("update:api-delete-data",data);
        },
        apiDuplicateRow:function({data,index,ignores}){
            var entity = JSON.parse(JSON.stringify(data));
            if(ignores){
              for(var i=0;i<ignores.length;i++){
                if(ignores[i]){
                  delete entity[ignores[i]];
                }
              }
            }
            delete entity['_XID']
            delete entity['_X_ROW_KEY']
            delete entity['_mcExtra']
            McCommon.util.addRow(this.tableData,entity,index)
        },
        /**
         * 设置表格数据 delete：处理deleteList的策略all:=全部数据 empty:=[] keep:保持不变
         * @param {data:[],count:0,code:0,delete:'all|empty|keep'} res
         */
        apiSetData:function(res){
          if(res.data==null){
            res.data=[];
          }
          if(res.delete=='all'){
              var table = this.tableData;
              this.apiSetDeleteData({data:JSON.parse(JSON.stringify(table))})
          }else if(res.delete == 'empty'){
              this.apiSetDeleteData({data:[]})
          }
          this._setTableData(res);
        },
        /**
         * executeBeforeSubmitForm 是否执行提交前验证 默认false 避免出现递归提交
         * @param param
         */
        submit:function (param) {
          param = param||{executeBeforeSubmitForm:false}
          this.submitForm(param);
        },
        getCheckedData:function () {
          return this.$refs.vxeTable.getCheckboxRecords();
        },
        getVxeTable:function () {
          return this.$refs.vxeTable;
        },
        getRowByRowIndex:function (rowIndex){
          if(this.tableData&&this.tableData.length>0){
            const rowId = this.getRowIdFromRowData(this.tableData[rowIndex]);
            return this.getRowById(rowId);
          }
          return null;
        },
        getRowById:function (rowId){
          return this.getVxeTable().getRowById(rowId);
        },
        apiGetParentScope:function () {
          return this.mcParentScope;
        },
        //{full:true,rowIndex:0,callback:({success,errMap}){}}
        validate:function (param) {
          if(window.MC){
            param = MC._.merge({full:false},param)
          }
          let validateRow = true;
          if(typeof  param.rowIndex!='undefined'){
            validateRow = this.getRowByRowIndex(param.rowIndex)
          }
          if(param.full){
              this.$refs.vxeTable.fullValidate(validateRow,( errMap )=>{
                if(param.callback){
                  param.callback({success:errMap==null,errMap:errMap})
                }
              }).catch(errMap => errMap)
          }else {
              this.$refs.vxeTable.validate(validateRow,( errMap )=>{
                if(param.callback){
                  param.callback({success:errMap==null,errMap:errMap})
                }
              }).catch(errMap => errMap)
          }
        },
        //同步校验
        asyncValidate:async function (param) {
          if(window.MC){
            param = MC._.merge({full:false},param)
          }
          let validateRow = true;
          if(typeof  param.rowIndex!='undefined'){
            validateRow = this.getRowByRowIndex(param.rowIndex)
          }
          var errMap = null;
          if(param.full){
            errMap = await this.$refs.vxeTable.fullValidate(validateRow).catch(errMap => errMap)
          }else {
            errMap = await this.$refs.vxeTable.validate(validateRow).catch(errMap => errMap)
          }
          return errMap;
        }
    },

}

</script>

<style lang="scss">
    /* .magicalcoder-dragging .mc-vxe-table .el-form.mc-vxe-table-form{
      position: relative;
    }
    .magicalcoder-dragging .mc-vxe-table .el-form.mc-vxe-table-form:before{
      content: 'scope.row';
      position: absolute;
      right: 0px;
      top: 0px;
      color:#4551ff;
      font-weight:bold;
      font-size: xx-small;
      float: right;
    } */
    .magicalcoder-dragging .mc-vxe-table{
      position: relative;
      padding: 10px;
      border: 1px solid #409EFF;
    }

    .magicalcoder-dragging .mc-vxe-table:before{
      content: '表格';
      position: absolute;
      right: 0px;
      top: 0px;
      color:#4551ff;
      font-weight:bold;
      font-size: xx-small;
      float: right;
    }
    /*.mc-vxe-table-dialog{
        .el-dialog {
            height: 80%;
            .el-dialog__body {
                height : 70%;
                overflow-y: auto;
                .mc-ui-absolute-pane{
                    position: relative;
                    height : 100%;
                }
            }
            .el-dialog__footer{
                position: absolute;
                right:0;
                bottom:0;
            }

        }
    }*/
    .mc-vxe-table:not(.mc-vxe-table-full-height)>.el-row>.el-col{
      margin-top:10px;
    }
    .mc-bg-transparent{
      .vxe-table--render-default{
          .vxe-table--body-wrapper{
            background-color: unset;
          }
          .vxe-table--footer-wrapper{
            background-color: unset;
          }
      }
      .vxe-table--render-default.border--default{
          .vxe-table--header-wrapper{
            background-color: unset;
          }
      }
      .vxe-table--render-default.border--full{
        .vxe-table--header-wrapper{
          background-color: unset;
        }
      }
      .vxe-table--render-default.border--outer{
        .vxe-table--header-wrapper{
          background-color: unset;
        }
      }
      .vxe-table--render-default.border--none{
        .vxe-table--header-wrapper{
          background-color: unset;
        }
      }
      .vxe-table--render-default.border--inner{
        .vxe-table--header-wrapper{
          background-color: unset;
        }
      }
    }
    .mc-scroll-y-hidden{
      .vxe-table--body-wrapper, .vxe-table--fixed-left-body-wrapper,.vxe-table--fixed-right-body-wrapper{
        overflow-y:hidden;
      }
    }
    .mc-vxe-table-full-height{
      height:100%;
      .mc-vxe-table-row{
        height: 100%;
        .mc-vxe-table-col{
          height: 100%;
        }
      }
    }
    .mc-vxe-table-row-query-left{
      padding-right: 10px;
    }
    /*单元格校验的时候 如果一行 竟然被隐藏了*/
  .vxe-table--tooltip-wrapper.theme--dark.placement--top.is--visible.vxe-table--valid-error{
    z-index:3000!important;
  }
</style>
